<template>
  <div class="question-container">
    <!-- 图片展示区域 -->
    <div class="image-display">
      <el-skeleton v-if="isLoading" animated>
        <template #template>
          <el-skeleton-item variant="image" style="width: 100%; height: 300px" />
        </template>
      </el-skeleton>
      <el-image
        v-else
        :src="currentQuestion.imageUrl"
        :alt="currentQuestion.imageAlt"
        fit="contain"
      />
    </div>

    <!-- 音频选项区域 -->
    <div class="audio-choices">
      <el-space direction="vertical" :size="20" fill>
        <div
          v-for="choice in currentQuestion.choices"
          :key="choice.id"
          class="audio-choice"
          :class="{
            'is-selected': selectedChoiceId === choice.id,
            'is-correct': hasAnswered && choice.isCorrect,
            'is-incorrect': hasAnswered && selectedChoiceId === choice.id && !choice.isCorrect,
            'is-disabled': hasAnswered,
          }"
          @click="handleChoiceClick(choice)"
        >
          <div class="audio-choice-content">
            <el-button
              circle
              :icon="playing === choice.id ? 'Pause' : 'VideoPlay'"
              :disabled="hasAnswered"
            />
            <div class="audio-wave" :class="{ 'is-playing': playing === choice.id }">
              <!-- 音频波形动画 -->
              <div v-for="n in 5" :key="n" class="wave-bar"></div>
            </div>

            <!-- 答案状态图标 -->
            <div v-if="hasAnswered" class="answer-status">
              <el-icon v-if="choice.isCorrect" class="correct-icon">
                <CircleCheckFilled />
              </el-icon>
              <el-icon v-else-if="selectedChoiceId === choice.id" class="incorrect-icon">
                <CircleCloseFilled />
              </el-icon>
            </div>
          </div>
        </div>
      </el-space>
    </div>

    <!-- 提交按钮 -->
    <div class="submit-area" v-if="!hasAnswered">
      <el-button type="primary" :disabled="!selectedChoiceId" @click="checkAnswer">
        确认答案
      </el-button>
    </div>

    <!-- 答案反馈 -->
    <div v-if="hasAnswered" class="feedback-area">
      <el-alert
        :title="feedbackMessage"
        :type="isCorrectAnswer ? 'success' : 'error'"
        :closable="false"
        show-icon
        class="feedback-message"
      />
    </div>
  </div>
</template>

<script setup lang="ts">
import { ref, computed, watch, onUnmounted } from 'vue'
import { CircleCheckFilled, CircleCloseFilled } from '@element-plus/icons-vue'
import { ElMessage } from 'element-plus'
import axios from 'axios'
import type { Word } from '@/types/training'
import { base64ToBlob, createAudioElement, playAudio, cleanupAudio } from '@/utils/audioUtils'

interface AudioChoice {
  id: string
  audioUrl: string
  isCorrect: boolean
}

interface ImageResponse {
  alt: string
  url: string
}

interface Question {
  text: string
  imageUrl: string
  imageAlt: string
  choices: AudioChoice[]
}

interface Props {
  audio: {
    words: Word[]
  }
  images: {
    words: Word[]
  }
}

const props = withDefaults(defineProps<Props>(), {
  audio: () => ({
    words: [] as Word[],
  }),
  images: () => ({
    words: [] as Word[],
  }),
})

const emit = defineEmits<{
  (e: 'complete'): void
}>()

const questions = ref<Question>()
const selectedChoiceId = ref<string>('')
const isLoading = ref(false)
const hasAnswered = ref(false)
const playing = ref<string | null>(null)
const currentAudio = ref<HTMLAudioElement | null>(null)
const audioBlobUrls = ref<Map<string, string>>(new Map())

// 计算当前问题
const currentQuestion = computed(
  () =>
    questions.value || {
      imageUrl: '',
      imageAlt: '',
      choices: [],
    },
)

// 计算属性
const isCorrectAnswer = computed(() => {
  const selectedChoice = currentQuestion.value.choices.find(
    (choice) => choice.id === selectedChoiceId.value,
  )
  return selectedChoice?.isCorrect || false
})

const feedbackMessage = computed(() => {
  return isCorrectAnswer.value ? '回答正确！' : '回答错误！'
})

// 清理音频资源
const cleanupCurrentAudio = () => {
  if (currentAudio.value) {
    cleanupAudio(currentAudio.value)
    currentAudio.value = null
  }
  playing.value = null
}

// 清理 Blob URLs
const cleanupBlobUrls = () => {
  audioBlobUrls.value.forEach((url) => {
    URL.revokeObjectURL(url)
  })
  audioBlobUrls.value.clear()
}

// 获取题目数据
const fetchQuestions = async () => {
  console.log('fetchQuestions called')
  console.log('currentPage words:', props.audio.words)

  if (!props.audio.words?.length) {
    console.log('No words in currentPage')
    return
  }

  // 清理之前的音频资源
  cleanupCurrentAudio()
  cleanupBlobUrls()

  isLoading.value = true
  try {
    // 并行处理所有音频请求
    const audioPromises = props.audio.words.map(async (word, index) => {
      const response = await axios.post(`/api/audio/base64?text=${encodeURIComponent(word.text)}`)
      const base64Audio = response.data

      // 转换为 Blob URL
      const audioBlob = base64ToBlob(base64Audio, 'audio/mp3')
      const blobUrl = URL.createObjectURL(audioBlob)

      // 存储 Blob URL
      const choiceId = (index + 1).toString()
      audioBlobUrls.value.set(choiceId, blobUrl)

      return {
        id: choiceId,
        audioUrl: blobUrl,
        isCorrect: word.isCorrect || false,
        text: word.text,
      }
    })

    // 图片请求（仅处理第一个图片单词）
    const imageWord = props.images.words[0]
    const imagePromise = imageWord
      ? axios.post(`/api/pic/getUrl?prompt=${encodeURIComponent(imageWord.text)}`)
      : Promise.resolve({ data: [] })

    // 并发执行所有请求
    const [audioResults, imageResponse] = await Promise.all([
      Promise.all(audioPromises),
      imagePromise,
    ])

    // 准备图片数据（处理可能为空的情况）
    const imageData: ImageResponse[] = imageResponse.data || []
    const firstImage = imageData[0] || {}

    // 动态构建选择题选项
    questions.value = {
      text: imageWord?.text || '未提供图片描述',
      imageUrl: firstImage.url || '',
      imageAlt: firstImage.alt || imageWord?.text || '',
      choices: audioResults,
    }
  } catch (error) {
    console.error('数据获取失败:', error)
    // 创建安全默认值
    questions.value = {
      text: '数据加载失败',
      imageUrl: '',
      imageAlt: '加载失败',
      choices: props.audio.words.map((word, index) => ({
        id: (index + 1).toString(),
        audioUrl: '',
        isCorrect: word.isCorrect || false,
        text: word.text,
      })),
    }
    ElMessage.error('获取题目失败，请稍后重试')
  } finally {
    isLoading.value = false
  }
}

// 监听 props 变化
watch(
  () => props.images.words,
  (newVal) => {
    console.log('currentPage changed:', newVal)
    if (newVal) {
      fetchQuestions()
    }
  },
  { immediate: true },
)

// 处理选项点击
const handleChoiceClick = (choice: AudioChoice) => {
  if (!hasAnswered.value) {
    selectedChoiceId.value = choice.id
    toggleAudio(choice)
  }
}

// 检查答案
const checkAnswer = () => {
  const selectedChoice = currentQuestion.value.choices.find(
    (choice) => choice.id === selectedChoiceId.value,
  )

  if (selectedChoice) {
    hasAnswered.value = true
    if (selectedChoice.isCorrect) {
      ElMessage.success('回答正确！')
      emit('complete')
    } else {
      ElMessage.error('回答错误！')
    }
  }
}

// 切换音频播放
const toggleAudio = async (choice: AudioChoice) => {
  try {
    // 如果点击的是当前正在播放的音频，则停止播放
    if (playing.value === choice.id) {
      cleanupCurrentAudio()
      return
    }

    // 停止当前播放的音频
    cleanupCurrentAudio()

    // 检查音频 URL 是否有效
    if (!choice.audioUrl) {
      ElMessage.error('音频数据无效')
      return
    }

    // 使用工具函数创建和加载音频
    currentAudio.value = await createAudioElement(choice.audioUrl, {
      timeout: 10000,
    })

    // 开始播放
    await playAudio(currentAudio.value)
    playing.value = choice.id

    // 监听播放结束
    currentAudio.value.addEventListener('ended', () => {
      playing.value = null
    })

    // 监听播放错误
    /*currentAudio.value.addEventListener('error', (e) => {
      console.error('音频播放错误:', e)
      playing.value = null
      ElMessage.error('音频播放失败')
    })*/
  } catch (error) {
    console.error('音频播放失败:', error)
    ElMessage.error('音频播放失败，请稍后重试')
    playing.value = null
    cleanupCurrentAudio()
  }
}

// 组件卸载时清理资源
onUnmounted(() => {
  cleanupCurrentAudio()
  cleanupBlobUrls()
})
</script>

<style scoped>
.question-container {
  display: flex;
  flex-direction: column;
  gap: 1.5rem;
  align-items: center;
  width: 100%;
  max-width: 800px;
  margin: 0 auto;
  padding: 12px;
  min-height: 100vh;
  background-color: #f5f7fa;
}

.image-display {
  width: 100%;
  max-height: 300px;
  display: flex;
  justify-content: center;
  align-items: center;
  overflow: hidden;
  border-radius: 16px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
  background: #fff;
}

.audio-choices {
  width: 100%;
  padding: 0 12px;
}

.audio-choice {
  width: 100%;
  cursor: pointer;
  transition: all 0.3s ease;
  margin-bottom: 12px;
}

.audio-choice.is-disabled {
  cursor: not-allowed;
}

.audio-choice-content {
  display: flex;
  align-items: center;
  gap: 12px;
  padding: 12px;
  border-radius: 12px;
  background-color: #fff;
  border: 2px solid transparent;
  transition: all 0.3s ease;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.05);
}

.audio-choice.is-selected .audio-choice-content {
  border-color: var(--el-color-primary);
  background-color: var(--el-color-primary-light-9);
}

.audio-choice.is-correct .audio-choice-content {
  border-color: var(--el-color-success);
  background-color: var(--el-color-success-light-9);
}

.audio-choice.is-incorrect .audio-choice-content {
  border-color: var(--el-color-danger);
  background-color: var(--el-color-danger-light-9);
}

.audio-wave {
  display: flex;
  align-items: center;
  gap: 3px;
  height: 24px;
  flex: 1;
}

.wave-bar {
  width: 3px;
  height: 100%;
  background-color: var(--el-text-color-secondary);
  border-radius: 2px;
  transform: scaleY(0.3);
  transition: transform 0.2s ease;
}

.audio-wave.is-playing .wave-bar {
  animation: wave 1s ease-in-out infinite;
}

.wave-bar:nth-child(1) {
  animation-delay: 0s;
}
.wave-bar:nth-child(2) {
  animation-delay: 0.2s;
}
.wave-bar:nth-child(3) {
  animation-delay: 0.4s;
}
.wave-bar:nth-child(4) {
  animation-delay: 0.6s;
}
.wave-bar:nth-child(5) {
  animation-delay: 0.8s;
}

@keyframes wave {
  0%,
  100% {
    transform: scaleY(0.3);
  }
  50% {
    transform: scaleY(1);
  }
}

.answer-status {
  margin-left: auto;
  font-size: 18px;
}

.correct-icon {
  color: var(--el-color-success);
}

.incorrect-icon {
  color: var(--el-color-danger);
}

.submit-area {
  margin-top: 1.5rem;
  padding: 0 16px;
  width: 100%;
}

.submit-area .el-button {
  width: 100%;
  max-width: 300px;
  height: 44px;
  font-size: 16px;
  border-radius: 22px;
}

.feedback-area {
  margin-top: 1.5rem;
  padding: 0 16px;
  width: 100%;
  display: flex;
  flex-direction: column;
  gap: 16px;
}

.feedback-message {
  margin-bottom: 8px;
}

/* iPhone 特定样式 */
@supports (-webkit-touch-callout: none) {
  .question-container {
    padding-bottom: env(safe-area-inset-bottom);
  }

  .submit-area {
    padding-bottom: env(safe-area-inset-bottom);
  }

  .audio-choice {
    -webkit-tap-highlight-color: transparent;
  }

  .feedback-area {
    padding-bottom: env(safe-area-inset-bottom);
  }
}

/* 横屏模式 */
@media screen and (orientation: landscape) {
  .question-container {
    flex-direction: row;
    align-items: flex-start;
    padding: 16px;
  }

  .image-display {
    max-height: 400px;
    width: 50%;
  }

  .audio-choices {
    width: 50%;
    padding: 0 16px;
  }
}

/* 小屏幕设备 */
@media screen and (max-width: 375px) {
  .question-container {
    gap: 1rem;
  }

  .image-display {
    max-height: 250px;
  }

  .audio-choice-content {
    padding: 10px;
  }

  .wave-bar {
    width: 2px;
  }
}
</style>
